package com.ruoyi.framework.mybatisplus;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.framework.mybatisplus.strategy.QueryStrategy;
import com.ruoyi.framework.mybatisplus.strategy.QueryStrategyFactory;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/**
 * 动态查询工具类，用于MyBatis Plus
 * 支持动态构建查询条件，包括：
 * 1. 支持多种查询操作符（等于、模糊、大于、小于等）
 * 2. 支持字段别名
 * 3. 支持分页查询
 * 4. 支持结果转换
 * 
 * @author xuzhen97
 */
public final class DynamicOperate {

    /**
     * 跳过字段， queryWrapper中跳过
     */
    private static final List<String> SKIP_FIELDS = Arrays.asList("pageNum", "pageSize");

    /**
     * 列表查询
     * 支持结果转换
     * 
     * @param qry           查询指令
     * @param mapper        查询mapper
     * @param skipFields    需要跳过的字段
     * @param <T>           数据库实体
     * @param <K>           查询指令
     * @return 转换后的结果列表
     */
    public static <T, K> List<T> list(K qry
            , BaseMapper<T> mapper, String... skipFields) {
        QueryWrapper<T> queryWrapper = queryWrapper(qry, skipFields);
        return mapper.selectList(queryWrapper);
    }

    /**
     * 分页查询
     * 
     * @param qry 查询指令
     * @param mapper 查询mapper
     * @return 分页结果
     * @param <T> 数据库实体
     * @param <K> 查询指令
     */
    public static <T,K extends PageQry> Page<T> page(K qry
            , BaseMapper<T> mapper){
        QueryWrapper<T> queryWrapper = queryWrapper(qry);
        return mapper.selectPage(new Page<>(qry.getPageNum(), qry.getPageSize()), queryWrapper);
    }

    /**
     * 根据实体命令生成QueryWrapper条件
     * 支持只作为参数传递的字段（如HAVING用）和跳过字段
     * 
     * @param qry 查询对象
     * @param onlyParamFields 只作为参数传递的字段（不参与where）
     * @param <T> 实体类型
     * @return QueryWrapper
     */
    public static <T> QueryWrapper<T> queryWrapper(Object qry, String... onlyParamFields) {
        Map<String, Field> fieldMap = ReflectUtil.getFieldMap(qry.getClass());
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        List<String> onlyParamList = onlyParamFields == null ? Collections.emptyList() : Arrays.asList(onlyParamFields);

        for (Map.Entry<String, Field> entry : fieldMap.entrySet()) {
            String key = entry.getKey();
            Field field = entry.getValue();
            Object value = ReflectUtil.getFieldValue(qry, field);

            // 处理参数传递字段
            if (onlyParamList.contains(key)) {
                if (ObjectUtil.isNotEmpty(value)) {
                    queryWrapper.getParamNameValuePairs().put(key, value);
                }
                continue;
            }

            // 跳过分页等字段
            if (SKIP_FIELDS.contains(key)) {
                continue;
            }

            // 使用策略模式处理查询条件
            QueryStrategy strategy = QueryStrategyFactory.getStrategy(key);
            strategy.apply("", qry, key, field, queryWrapper);
        }
        return queryWrapper;
    }

    /**
     * 根据实体命令生成QueryWrapper条件
     * 
     * @param qry 查询对象
     * @param <T> 实体类型
     * @return QueryWrapper
     */
    public static <T> QueryWrapper<T> queryWrapper(Object qry) {
        return queryWrapper(qry, new String[0]);
    }
}
